package s

import (
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"regexp"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

var (
	FormatRe            = regexp.MustCompile(`(\{\w+?\})`)
	FileRe              = regexp.MustCompile(`(\@[\\\/\w\.\_\-\(\)\~]+)`)
	ANSI_LINE_UP        = "A"
	ANSI_LINE_DOWN      = "B"
	ANSI_LINE_NEXT_LINE = "E"
	ANSI_LINE_PRE_LINE  = "F"

	ANSI_CURSOR_MOVE        = "H"
	ANSI_CURSOR_SAVE        = "s"
	ANSI_CURSOR_SAVE_DARWIN = "7"

	ANSI_CURSOR_RESTORE        = "u"
	ANSI_CURSOR_RESTORE_DARWIN = "8"

	ANSI_COLUMN_MOVE  = "G"
	ANSI_COLUMN_RIGHT = "C"
	ANSI_COLUMN_LEFT  = "D"

	ANSI_ERASE_ALL_TOEND  = "0J"
	ANSI_ERASE_ALL_BEFORE = "1J"
	ANSI_ERASE_ALL_SCREEN = "2J"

	ANSI_THIS_LINE_ERASE_TOEND  = "0K"
	ANSI_THIS_LINE_ERASE_BEFORE = "1K"
	ANSI_THIS_LINE_ERASE_ALL    = "2K"

	ANSI_STYLE = "m"

	ANSI_STYLE_RESET              = 0
	ANSI_STYLE_BOLD               = 1
	ANSI_STYLE_DIM_FAINT          = 2
	ANSI_STYLE_ITALIC             = 3
	ANSI_STYLE_UNDERLINE          = 4
	ANSI_STYLE_BLINK              = 5
	ANSI_STYLE_REVERSE            = 7
	ANSI_CURSOR_HIDDEN_OR_DISPLAY = 8
	ANSI_STYLE_STRIKELINE         = 9

	FgBlack    = 30
	BGBlack    = 40
	FgRed      = 31
	BgRed      = 41
	FgGreen    = 32
	BgGreen    = 42
	FgYellow   = 33
	FgBgYellow = 43
	FgBlue     = 34
	BgBlue     = 44
	FgMagenta  = 35
	BgMagenta  = 45
	FgCyan     = 36
	BgCyan     = 46
	FgWhite    = 37
	BgWhite    = 47
	FgDefault  = 39
	BgDefault  = 49

	NOT    = 0x10010111
	EXCEPT = 0x10010112
	IN     = 0x10010003
	TO     = 0x10010004
	BEFORE = 0x10011015
	AFTER  = 0x10011016
	FROM   = 0x10010117
	LAST   = 0x10010118
)

type Str string
type List[T any] []T

type EStr struct {
	Str
	Start int
	End   int
	Next  int
}

type Dict[K comparable, T any] map[K]T

func (d Dict[K, T]) Keys() List[K] {
	e := List[K]{}
	for i := range d {
		e = e.Push(i)
	}
	return e
}

func (self EStr) String() string {
	return self.Str.String()
}

func (d Dict[K, T]) Each(do func(k K, v T)) Dict[K, T] {
	for k, v := range d {
		do(k, v)
	}
	return d
}

func (d Dict[K, T]) Len() int {
	return len(d)
}

func (d Dict[K, T]) EveryWith(do func(k K, v T) T) Dict[K, T] {
	cl := sync.RWMutex{}
	for k, v := range d {
		nv := do(k, v)
		cl.Lock()
		d[k] = nv
		cl.Unlock()
	}
	return d
}

func (d Dict[k, T]) Values() List[T] {
	e := List[T]{}
	for _, i := range d {
		e = e.Push(i)
	}
	return e
}

func (d Dict[K, T]) Any(comkey func(k K, v T) bool) (outk K, outv T, found bool) {
	for tmpk, tmpv := range d {
		if comkey(tmpk, tmpv) {
			return tmpk, tmpv, true
		}
	}
	return
}

func Tr(a any) interface{} {
	return a
}

func (dict Dict[K, T]) AsIniStr(tmp, sep Str, sec ...Str) Str {
	res, err := dict.AsStr(`{key} = {val}`, "\n", "\n[{key}]\n")
	if err != nil {
		return ""
	}
	return "[base]\n" + res
}

func (dict Dict[K, T]) AsStr(tmp, sep Str, sec ...Str) (Str, error) {
	if !tmp.Has("{key}") || !tmp.Has("{val}") {
		return "", fmt.Errorf("tmp must has '{key}' and '{val}' %s", "")
	}
	e := Str("")
	stacks := []any{}
	for k, v := range dict {
		if e != "" {
			e += sep
		}

		if v2, ok := Tr(v).(Dict[K, T]); ok {
			// fmt.Println(v, ok)
			stacks = append(stacks, k, v2)

			continue
		}

		e += tmp.Format(Dict[Str, any]{"key": k, "val": v})
	}
	for len(stacks) > 0 {
		k := stacks[0].(Str)
		v2 := stacks[1].(Dict[K, T])
		stacks = stacks[2:]
		if sec != nil {
			e += sec[0].Format(Dict[Str, any]{
				"key": k,
			})
		} else {
			e += sep
		}
		if esub, err := v2.AsStr(tmp, sep, sec...); err != nil {
			return "", err
		} else {
			e += esub
		}
	}
	return e, nil
}

func (d Dict[k, T]) Json() (Str, error) {
	e, err := json.Marshal(&d)
	if err != nil {
		return "", err
	}
	return Str(e), nil
}

func (s List[T]) Len() int {
	return len(s)
}

func (s List[T]) Last() T {
	return s[s.Len()-1]
}

func (s List[T]) Has(b T, eq func(a, b T) bool) bool {
	for _, i := range s {
		if eq != nil {
			if eq(i, b) {
				return true
			}
		}
	}
	return false
}

func (s List[T]) Reverse() (nl List[T]) {
	for i := s.Len() - 1; i > -1; i-- {
		nl = append(nl, s[i])
	}
	return
}

// Slice extract sub slice
func (s List[T]) Slice(start int, end ...int) List[T] {
	if start < 0 {
		start += s.Len()
	}
	if end != nil {
		ends := end[0]
		if ends < 0 {
			ends += s.Len()
		}
		return s[start:ends]
	} else {

		return s[start:]
	}
}

func (s List[T]) Any(key func(i int, v T) bool) (out T, found bool) {
	for tmpi, tmpt := range s {
		if key(tmpi, tmpt) {
			return tmpt, true
		}
	}
	return
}

func (s List[T]) Uniq() (uq List[T]) {
	e := make(Dict[Str, int])
	for ix, i := range s {
		e[Sprintf("%v", i)] = ix
	}
	for k := range e {
		uq = append(uq, s[e[k]])
	}
	return
}

// short of Slice
func (s List[T]) S(start int, end ...int) List[T] {
	return s.Slice(start, end...)
}

func SafePush[T any](s *List[T], o T) *List[T] {
	rw.Lock()
	defer rw.Unlock()
	*s = (*s).Push(o)
	return s
}

func SafePop[T any](s *List[T], ix ...int) T {
	rw.Lock()
	defer rw.Unlock()
	c := s.Pop(ix...)
	return c
}

func (s List[T]) Pop(ix ...int) T {
	i := s.Len() - 1
	if ix != nil {
		i = ix[0]
	}
	if i < 0 {
		i = s.Len() + i
	}
	e := s[i]
	if i == s.Len()-1 {
		s = s[:i]
	} else {
		s = append(s[:i], s[i+1:]...)
	}
	return e
}
func (s List[T]) Push(body T) List[T] {

	s = append(s, body)
	return s
}

func (s List[T]) Count(b T, eq func(a, v T) bool) int {
	n := 0
	s.Each(func(i int, item T) {
		if eq(b, item) {
			n += 1
		}
	})
	return n
}

func (s List[T]) Index(body T, eq func(a, b T) bool) (ix int) {
	for ix := range s {
		if eq(s[ix], body) {
			return ix
		}
	}
	return -1
}

func (s List[T]) Filter(filterFunc func(i int, item T) bool) (nl List[T]) {
	for i, b := range s {
		if filterFunc(i, b) {
			nl = append(nl, b)
		}
	}
	return
}

func (s List[T]) EveryWith(do func(i int, item T) T) List[T] {
	nl := List[T]{}
	for no, item := range s {
		nl = append(nl, do(no, item))
	}
	return nl
}

func (s List[T]) MapWith(do func(i int, item T) any) (mp Dict[Str, any]) {
	mp = make(Dict[Str, any])
	s.Each(func(i int, item T) {
		ni := do(i, item)
		if ni == nil {
			return
		}
		mp[Str(fmt.Sprint(item))] = ni
	})
	return
}

func (s List[T]) Join(sepIfNoIsSpace ...string) Str {
	sep := " "
	if sepIfNoIsSpace != nil {
		sep = sepIfNoIsSpace[0]
	}
	ess := []string{}
	s.Each(func(i int, item T) {
		ess = append(ess, fmt.Sprint(item))
	})
	return Str(strings.Join(ess, sep))
}

func (s List[T]) Each(do func(i int, item T), asyncNum ...int) List[T] {
	if asyncNum != nil && asyncNum[0] > 1 {
		group := sync.WaitGroup{}
		for no, item := range s {
			group.Add(1)
			go func(item_ix int, itemBody T) {
				defer group.Done()
				do(item_ix, itemBody)
			}(no, item)
			if no > 0 && no%asyncNum[0] == 0 {
				group.Wait()
			}
		}

		group.Wait()

	} else {
		for no, item := range s {
			do(no, item)
		}

	}

	return s
}

func (s List[T]) Sort(compareFunc ...func(a T, b T) bool) List[T] {
	sort.Slice(s, func(i, j int) bool {
		if compareFunc != nil {
			return compareFunc[0](s[i], s[j])
		} else {

			a := fmt.Sprintf("%v", s[i])
			b := fmt.Sprintf("%v", s[j])
			ll := len(a)
			if len(a) != len(b) {
				return len(a) < len(b)
			}
			for i := 0; i < ll; i++ {
				if a[i] == b[i] {
					continue
				} else {
					return a[i] < b[i]
				}
			}

			return len(a) < len(b)
		}
	})
	return s
}

func (self Str) Strip() Str {
	return Str(strings.TrimSpace(self.String()))
}

func (self Str) StartWith(s string) bool {
	return strings.HasPrefix(string(self), s)
}

/* SubStr

select sub str :

	// 筛选 从 。。。 到 。。。。。
	x.SubStr(s.FROM, "<div>",s.TO, "</div>")
	// 更详细的选项有 第几个 或者最后一个如
	// 从第二个 <div> 到 最后一个  </div>
	x.SubStr(x.FROM , 2, "<div>", s.TO, s.LAST, "</div>")


*/
func (self Str) SubStr(limit ...any) Str {
	if limit == nil {
		return self.Copy()
	}
	Not := false
	In := false
	Before := false
	After := false
	// Except := false
	To := false
	From := false
	Last := false
	// Range := ExtractStr{Str: "", Start: -1, End: -1}
	Pre := ""
	End := ""
	sub := self.Copy()
	nst := -1
	for _, l := range limit {
		if i, ok := l.(int); ok {
			if i == NOT {
				Not = true
			} else if i == IN {
				In = true
			} else if i == BEFORE {
				Before = true
			} else if i == AFTER {
				After = true
			} else if i == TO {
				To = true
			} else if i == FROM {
				From = true
			} else if i == LAST {
				Last = true
			} else {
				nst = i
			}

		} else if limitRange, ok := l.(EStr); ok {
			if In {
				In = false
				if Not {
					sub = sub[:limitRange.Start] + sub[limitRange.End:]
				} else {
					sub = sub[limitRange.Start:limitRange.End]
				}
			} else {
				log.Fatal("ExStr must： IN xxExStr  or NOT IN xxExStr ")
			}
		} else if limitStr, ok := l.(string); ok {
			// end := limitPre
			if From {
				From = false
				if Last {
					Last = false
					sub = sub[sub.Index(limitStr, true):]

				} else if nst == -1 {
					sub = sub[sub.Index(limitStr):]
				} else {
					for i := 0; i < nst; i++ {
						sub = sub[sub.Index(limitStr):]
					}
					nst = -1
				}
			} else if Before {
				Before = false
				if Last {
					sub = sub[:sub.Index(limitStr, true)+len(limitStr)]
				} else if nst == -1 {
					sub = sub[:sub.Index(limitStr)+len(limitStr)]
				} else {
					cl := sub.Count(limitStr)
					// c := Str("")
					for i := 0; i < cl-nst+1; i++ {
						// c = sub[:sub.Index(limitStr)]
						sub = sub[:sub.Index(limitStr, true)+len(limitStr)]
					}
					nst = -1
				}
			} else if After {
				After = false
				if Last {
					Last = false
					sub = sub[sub.Index(limitStr, true):]

				} else if nst == -1 {
					sub = sub[sub.Index(limitStr):]
				} else {
					for i := 0; i < nst; i++ {
						sub = sub[sub.Index(limitStr):]
					}
					nst = -1
				}
			} else if To {
				To = false
				// fmt.Println(In, Pre)
				if In && Pre != "" {
					End = limitStr
					c := Str("")
					for _, ex := range sub.Extract(Pre, End) {
						c += ex.Str
					}
					sub = c
					Pre = ""
					End = ""
				} else if !In && Pre == "" {
					if Last {
						// fmt.Println("last:")
						sub = sub[:sub.Index(limitStr, true)+len(limitStr)]
					} else if nst == -1 {
						sub = sub[:sub.Index(limitStr)+len(limitStr)]
					} else {
						cl := sub.Count(limitStr)
						for i := 0; i < cl-nst+1; i++ {
							sub = sub[:sub.Index(limitStr, true)+len(limitStr)]
						}
						nst = -1
					}

				} else {
					log.Fatal("To must : 'FROM' xxx 'TO'   or In xxx 'TO' xx ")
				}

			} else if In {
				// if Pre != "" {
				Pre = limitStr
				// }
			}
		}
	}
	return sub
}

func (self Str) Count(sub string) int {
	return strings.Count(self.String(), sub)
}

func (self Str) Index(key string, fromLast ...bool) int {
	if fromLast != nil && fromLast[0] {
		return strings.LastIndex(self.String(), key)
	}
	return strings.Index(self.String(), key)
}

func (self Str) Has(s string, limit ...any) bool {
	if limit != nil {
		Not := false
		In := true
		Before := false
		After := false
		Except := false
		Pre := ""
		Range := EStr{Str: "", Start: -1, End: -1}
		End := ""
		for _, l := range limit {
			if i, ok := l.(int); ok {
				if i == NOT {
					Not = true
				} else if i == IN {
					In = true
				} else if i == BEFORE {
					Before = true
				} else if i == AFTER {
					After = true
				}

			} else if limitRange, ok := l.(EStr); ok {
				Range = limitRange
			} else if limitStr, ok := l.(string); ok {
				// end := limitPre
				if Pre == "" {
					Pre = limitStr
				} else {
					End = limitStr
				}
			}
		}
		if Pre != "" {
			if End == "" {
				End = Pre
			}
			if Except {
				Notraw := self.Copy()
				for _, exStr := range self.Extract(Pre, End) {
					Notraw = Notraw[:exStr.Start] + Notraw[exStr.End:]
				}
				return Notraw.Has(s)

			} else {
				// fmt.Println("Not:", Not)
				for _, exStr := range self.Extract(Pre, End) {
					// exStr.ANSIGreen().Println()
					if exStr.Has(s) {
						if Not {
							return false
						}
						return true
					}
				}
				if Not {
					return true
				}
				return false
			}

		} else if Range.Start != -1 {
			if In && !Not {
				return self[Range.Start:Range.End].Has(s)
			} else if Not && In {
				return self[:Range.Start].Has(s) || self[Range.End:].Has(s)
			} else if Before {
				return self[:Range.Start].Has(s)
			} else if After {
				return self[Range.End:].Has(s)
			}

			return self[Range.Start:Range.End].Has(s)

		}

	}
	return strings.Contains(self.String(), s)
}

func (self Str) EndWith(s string) bool {
	return strings.HasSuffix(string(self), s)
}

func (self Str) Copy() Str {
	return Str(self.String())
}

func (self Str) Split(s ...string) (ss List[Str]) {
	if s != nil {
		for _, i := range strings.Split(string(self), s[0]) {
			ss = append(ss, Str(i))
		}

	} else {

		for _, i := range strings.Fields(string(self)) {
			ss = append(ss, Str(i))
		}
	}
	return
}

func (self Str) Encode() Bytes {
	return []byte(self.String())
}

func (self Str) Len() int {
	return len(self)
}

func (self Str) Cut2(by string) (left, right Str) {
	fs := self.SplitQuote(by, 2)
	if len(fs) > 1 {
		left = fs[0].Strip()
		right = fs[1].Strip()
	} else {
		left = fs[0].Strip()
	}
	return
}

func (self Str) Cut3(by string) (left, mid, right Str) {
	fs := self.SplitQuote(by, 3)
	if len(fs) > 2 {
		left = fs[0].Strip()
		mid = fs[1].Strip()
		right = fs[2].Strip()
	} else if len(fs) > 1 {
		left = fs[0].Strip()
		mid = fs[1].Strip()
	} else {
		left = fs[0].Strip()

	}
	return
}

func (self Str) SplitQuote(by string, num int, quotes ...string) (ss List[Str]) {
	quoted := false
	key := ""
	c := ' '
	no := 1
	if quotes != nil {
		out := strings.FieldsFunc(self.String(), func(r rune) (ifsplit bool) {
			if key != "" && strings.HasPrefix(by, key+string(r)) {
				key += string(r)
			} else if by[0] == byte(r) {
				key += string(r)
			} else {
				key = ""
			}
			if !quoted && r == rune(quotes[0][0]) {
				c = r
				quoted = !quoted
			} else if quoted && r == rune(quotes[0][1]) {
				quoted = !quoted
			}

			ifsplit = !quoted && key == by
			if num < 0 {
				return
			}
			if ifsplit && no < num {
				no += 1
				return true
			} else {
				return false
			}
		})
		for _, i := range out {
			ss = append(ss, Str(i))
		}
	} else {
		out := strings.FieldsFunc(self.String(), func(r rune) (ifsplit bool) {
			if key != "" && strings.HasPrefix(by, key+string(r)) {
				key += string(r)
			} else if by[0] == byte(r) {
				key += string(r)
			} else {
				key = ""
			}
			if !quoted && (r == '"' || r == '\'') {
				c = r
				quoted = !quoted
			} else if quoted && r == c {
				quoted = !quoted
			}

			ifsplit = !quoted && key == by
			if num < 0 {
				return
			}
			if ifsplit && no < num {
				no += 1
				return true
			} else {
				return false
			}
		})

		for _, i := range out {
			ss = append(ss, Str(i))
		}
	}

	return
}

// A append in end
func (self Str) A(a any) Str {
	switch a.(type) {
	case string:
		builder := strings.Builder{}
		builder.WriteString(self.String())
		builder.WriteString(a.(string))
		return Str(builder.String())
	case Str:
		builder := strings.Builder{}
		builder.WriteString(self.String())
		builder.WriteString(a.(Str).String())
		return Str(builder.String())
	default:
		builder := strings.Builder{}
		builder.WriteString(self.String())
		builder.WriteString(fmt.Sprint(a))
		return Str(builder.String())
	}
}

// P prepend in start
func (self Str) P(a any) Str {
	switch a.(type) {
	case string:
		builder := strings.Builder{}
		builder.WriteString(a.(string))
		builder.WriteString(self.String())
		return Str(builder.String())
	case Str:
		builder := strings.Builder{}
		builder.WriteString(a.(Str).String())
		builder.WriteString(self.String())
		return Str(builder.String())
	default:
		builder := strings.Builder{}
		builder.WriteString(fmt.Sprint(a))
		builder.WriteString(self.String())
		return Str(builder.String())
	}
}

func (self Str) Trim(pre string, reverse ...bool) Str {
	if reverse != nil && reverse[0] {
		return Str(strings.TrimRight(string(self), pre))
	}
	return Str(strings.TrimLeft(string(self), pre))
}

func (self Str) String() string {
	return string(self)
}

func (self Str) ReFindAll(rex string) (ss List[Str]) {
	w, err := regexp.Compile(rex)
	if err != nil {
		return List[Str]{}
	}
	for _, ii := range w.FindAllString(string(self), -1) {
		ss = append(ss, Str(ii))
	}
	return
}

func (self Str) ReMatch(rex string) bool {
	w, err := regexp.Compile(rex)
	if err != nil {
		Str(err.Error()).ANSIRed().Println()
		return false
	}
	return w.MatchString(self.String())
}

func (self Str) TryAsInt() (int, error) {
	return strconv.Atoi(self.String())
}

func (self Str) TryAsFloat() (float64, error) {
	return strconv.ParseFloat(self.String(), 64)
}

func (self Str) Replace(i, e string, skip ...string) Str {
	if skip == nil {
		return Str(strings.ReplaceAll(self.String(), i, e))
	} else {
		pre := skip[0]
		end := skip[0]
		if len(skip) > 1 {
			end = skip[1]
		}
		st := 0
		et := self.Len() - 1
		newS := Str("")
		exs := self.Extract(pre, end)

		exs.Each(func(_ int, item EStr) {
			// item.Println()
			et = item.Start
			newS += self[st:et].Replace(i, e) + self[item.Start:item.Next]
			st = item.Next
			et = self.Len()
		})
		if st < et {
			newS += self[st:et].Replace(i, e)
		}
		return newS
	}
}

func (self Str) Remove(c string) Str {
	if len(c) == 2 {
		e := strings.Replace(self.String(), string(c[0]), "", 1)
		e = strings.Replace(e, string(c[1]), "", 1)
		return Str(e)
	}
	return self.Replace(c, "")
}

func (self Str) Eq(other string) bool {
	return self.String() == other
}

func (self Str) LastChar() string {
	if self.Len() == 0 {
		return ""
	}
	return string(self[self.Len()-1])
}

func (self Str) ExtractQuote() (ex List[EStr]) {
	return self.Extract("\"", "'", "`")
}

func (self Str) Extract(pre string, ends ...string) (ex List[EStr]) {
	windowsLen := len(pre)
	if ends != nil && len(ends) > 1 {
		ky := []string{pre}
		end := ""
		for _, k := range ends {
			if len(k) > windowsLen {
				windowsLen = len(k)
			}
			ky = append(ky, k)
		}

		entry := false
		jump := false
		one := Str("")
		start := -1
		for i := 0; i < self.Len()-windowsLen; i++ {
			windows := self[i : i+windowsLen]
			windowLastChar := windows.LastChar()
			// fmt.Println(windowLastChar)

			if windowLastChar == "\\" {
				jump = true
				if entry {
					one += Str(windowLastChar)
				}
				continue

			}

			if entry {
				if windows.EndWith(end) && !jump {
					// fmt.Println("End:", windows)
					// fmt.Println("Now:", one)
					if one.Len() > 0 {
						ex = append(ex, EStr{
							Str:   Str(pre) + one + Str(end),
							Start: start,
							End:   i + windowsLen - len(end),
							Next:  i + windowsLen,
						})
					}
					one = Str("")
					end = ""
					pre = ""
					entry = false
				} else {
					one += Str(windowLastChar)
				}
			} else if !jump {
				for _, k := range ky {
					if windows.EndWith(k) {
						pre = k
						entry = true
						end = k
						start = i + windowsLen - len(k)
						break
					}
				}
			}

			if jump {
				jump = false
				// continue
			}
		}
	} else {

		end := pre
		if ends != nil {
			end = ends[0]
		}

		if len(end) > windowsLen {
			windowsLen = len(end)
		}
		entry := false
		jump := false
		one := Str("")
		start := -1
		for i := 0; i < self.Len()-windowsLen; i++ {
			windows := self[i : i+windowsLen]
			windowLastChar := windows.LastChar()
			// fmt.Println(windowLastChar)

			if windowLastChar == "\\" {
				jump = true
				if entry {
					one += Str(windowLastChar)
				}
				continue

			}

			if entry {
				if len(end) > len(pre) && one.Len() < len(end)-len(pre) {
					jump = true
				}
				if windows.EndWith(end) && !jump {
					// fmt.Println("End:", windows)
					// fmt.Println("Now:", one[:len(one)])
					if one.Len() > 0 {

						ex = append(ex, EStr{
							Str:   Str(pre) + one[:one.Len()-len(end)+1] + Str(end),
							Start: start,
							End:   i + windowsLen - len(end),
							Next:  i + windowsLen,
						})
					}
					one = Str("")
					entry = false
				} else {
					// if windowLastChar == "\n" {
					// fmt.Println(one)
					// fmt.Println("win:", windows, "|||")

					// }
					one += Str(windowLastChar)
				}
			} else if windows.EndWith(pre) && !jump {
				entry = true
				start = i + windowsLen - len(pre)
			}

			if jump {
				jump = false
				// continue
			}
		}

	}

	return
}

func (self Str) Format(args Dict[Str, any]) (n Str) {
	// es := map[string]string{}
	n = Str(self.String())
	for _, i := range FormatRe.FindAllString(self.String(), -1) {
		key := Str(i).Remove("{}")
		if v, ok := args[key]; ok {
			n = n.Replace(i, fmt.Sprint(v))
		}
	}
	return
}

func (self Str) TryAsJson(buildStruct *interface{}) (Dict[string, any], error) {
	if buildStruct != nil {
		err := json.Unmarshal([]byte(self.String()), buildStruct)
		if err != nil {
			return nil, err
		}
		return nil, nil
	} else {
		e := make(map[string]any)
		err := json.Unmarshal([]byte(self.String()), &e)
		if err != nil {
			return nil, err
		}
		return e, nil
	}
}

func (self Str) ParseAsArgument() (args List[Str], kargs Dict[Str, Str]) {
	kargs = make(Dict[Str, Str])
	self.SplitQuote(",", -1).Each(func(i int, item Str) {
		if item.Has("=") {
			k, v := item.Cut2("=")
			kargs[k] = v
		} else {
			args = append(args, item.Strip())
		}
	})
	return
}

func (self Str) ParseAsIniArg() (kargs Dict[Str, any]) {
	tmpkargs := make(Dict[Str, any], 10)
	// fint := 0
	self.SplitQuote("\n", -1).Each(func(i int, item Str) {
		if item.Has("=") {
			k, v := item.Cut2("=")
			if v == "false" || v == "False" || v == "True" || v == "true" {
				vb, _ := strconv.ParseBool(strings.ToLower(v.String()))
				flag.BoolVar(&vb, k.String(), vb, k.P("value of ").A(Sprintf(" default:%v", vb)).String())
				tmpkargs[k] = &vb

			} else {
				v := v.String()
				flag.StringVar(&v, k.String(), v, k.P("value of ").A(Sprintf(" default:%v", v)).String())
				tmpkargs[k] = &v
			}

		}
	})

	Args()
	kargs = make(Dict[Str, any], 10)
	tmpkargs.Each(func(k Str, v any) {
		switch v.(type) {
		case *string:
			cv := v.(*string)
			if cv != nil {
				kargs[k] = *cv
			}
		case *bool:

			cv := v.(*bool)
			if cv != nil {
				kargs[k] = *cv
			}
		}
	})
	return kargs

}

func (self Str) ParseHex(key ...string) []byte {
	c, _ := hex.DecodeString(self.String())
	out := []byte{}
	if key != nil {
		for i, ci := range c {
			ki := key[0][i%len(key[0])]
			out = append(out, ci^ki)
		}
		return out
	}
	return c
}

func (self Str) Hex(key ...string) Str {
	b := []byte(self)
	b2 := []byte{}
	if key != nil {
		for i, ci := range b {
			ki := key[0][i%len(key[0])]
			// b[i] = ci ^ ki
			b2 = append(b2, ci^ki)
		}
		return Str(hex.EncodeToString(b2))

	}
	return Str(hex.EncodeToString(b))
	// return c
}

func (self Str) Join(lst ...any) Str {

	ss := []string{}
	list := List[any]{}

	for _, item := range lst {
		list = append(list, item)
	}
	// tp := reflect.TypeOf(lst)

	// join[](lst, "")
	//  ok {
	// cc := List[any](list)
	list.Each(func(i int, item any) {
		ss = append(ss, fmt.Sprint(item))
	})
	return Str(strings.Join(ss, self.String()))
	// } else {
	// 	fmt.Println("can not conver", lst)
	// 	return Str("")
	// }
}

type Chars List[byte]

func (self Str) AsCharacters() Chars {
	o := Chars{}
	for _, b := range []byte(self) {
		o = append(o, b)
	}
	return o
}

func (self Chars) Join(a rune) Str {
	c := Str("")
	for i, ci := range self {
		if i != 0 {
			c += Str(a)
		}
		c += Str(ci)
	}
	return c
}

func (self Str) ANSI(ANSI_FUNC_C string, ANSI_ARGS ...int) Str {
	args := Str("")
	if ANSI_ARGS != nil {
		// join[int](",", ANSI_ARGS)
		es := []string{}
		for _, code := range ANSI_ARGS {
			es = append(es, fmt.Sprint(code))
		}
		args = Str(strings.Join(es, ";"))
	}
	// print(args,)
	return Str(fmt.Sprintf("\x1b[%s%s", args, ANSI_FUNC_C))
}

func (self Str) ANSICursor(line, column int) Str {
	return self + self.ANSI(ANSI_CURSOR_MOVE, line, column)
}

func (self Str) ANSIPreLine() Str {
	return self + self.ANSI(ANSI_LINE_PRE_LINE)
}

func (self Str) ANSIEraseALL() Str {
	return self + self.ANSI(ANSI_ERASE_ALL_SCREEN)
}

func (self Str) ANSIClearThisLine() Str {
	return self + self.ANSI(ANSI_THIS_LINE_ERASE_TOEND)
}

func (self Str) ANSIEraseToEND() Str {
	return self + self.ANSI(ANSI_ERASE_ALL_TOEND)
}

func (self Str) ANSISave() Str {
	if runtime.GOOS == "darwin" {
		return self + Sprintf("\x1b%s", ANSI_CURSOR_SAVE_DARWIN)
	}

	return self + self.ANSI(ANSI_CURSOR_SAVE)
}

func (self Str) ANSIRestore() Str {
	if runtime.GOOS == "darwin" {
		return self + Sprintf("\x1b%s", ANSI_CURSOR_RESTORE_DARWIN)
	}
	return self + self.ANSI(ANSI_CURSOR_RESTORE)
}

func (self Str) ANSIHideOrDisCursor() Str {
	return self + self.ANSI(ANSI_STYLE, ANSI_CURSOR_HIDDEN_OR_DISPLAY)
}

func (self Str) ansi_end() Str {
	if self.EndWith("\x1b[0m") {
		return self
	} else {
		return self.A("\x1b[0m")
	}
}
func (self Str) ANSISelected() Str {

	return self.ANSI(ANSI_STYLE, ANSI_STYLE_REVERSE) + self.ansi_end()
}

func (self Str) ANSIStyle(ansiColorCode ...int) Str {
	return self.ANSI(ANSI_STYLE, ansiColorCode...) + self.ansi_end()
}

func (self Str) ANSIBold() Str {
	return self.ANSI(ANSI_STYLE, ANSI_STYLE_BOLD) + self.ansi_end()
}

func (self Str) ANSIStrike() Str {
	if runtime.GOOS == "darwin" {
		return self.AsCharacters().Join('\u0336').P("\u0336")
	}
	return self.ANSI(ANSI_STYLE, ANSI_STYLE_STRIKELINE) + self.ansi_end()
}

func (self Str) ANSIBlink() Str {
	return self.ANSI(ANSI_STYLE, ANSI_STYLE_BLINK) + self.ansi_end()
}

func (self Str) ANSIRed() Str {
	return self.ANSI(ANSI_STYLE, FgRed) + self.ansi_end()
}

func (self Str) ANSIMagenta() Str {
	return self.ANSI(ANSI_STYLE, FgMagenta) + self.ansi_end()
}

func (self Str) ANSIItalic() Str {
	return self.ANSI(ANSI_STYLE, ANSI_STYLE_ITALIC) + self.ansi_end()
}

func (self Str) ANSICyan() Str {
	return self.ANSI(ANSI_STYLE, FgCyan) + self.ansi_end()
}

func (self Str) ANSIGreen() Str {
	return self.ANSI(ANSI_STYLE, FgGreen) + self.ansi_end()
}

func (self Str) ANSIYellow() Str {
	return self.ANSI(ANSI_STYLE, FgYellow) + self.ansi_end()
}

func (self Str) ANSIBlue() Str {
	return self.ANSI(ANSI_STYLE, FgBlue) + self.ansi_end()
}

func (self Str) ANSIUnderline() Str {
	return self.ANSI(ANSI_STYLE, ANSI_STYLE_UNDERLINE) + self.ansi_end()
}

func (self Str) ANSIDimFaint() Str {
	return self.ANSI(ANSI_STYLE, ANSI_STYLE_DIM_FAINT) + self.ansi_end()
}

func (self Str) ANSIReset() Str {
	return self.ANSI(ANSI_STYLE, ANSI_STYLE_RESET) + self.ansi_end()
}

func (self Str) Pre(s string) Str {
	return Str(s) + self
}

func (self Str) Println(pre ...any) Str {
	if pre != nil {
		pre = append(pre, self)
		fmt.Println(pre...)

	} else {
		fmt.Println(self)

	}
	return self
}

func (self Str) Words() (wl List[Str]) {
	return self.ReFindAll(`\w+`).Uniq().Sort().Reverse()
}

func (self Str) ANSIRandomBeautiful() Str {
	rand.Seed(int64(time.Now().Second()))
	self.Words().Each(func(i int, item Str) {
		if item.Len() < 4 {

			return
		}

		randI := rand.Int() % 100
		color := randI % 14

		c2 := item.Copy()
		switch color {
		case 0:
			c2 = c2.ANSIStyle(FgBlack)
		case 1:
			c2 = c2.ANSIStyle(FgBlue)
		case 2:
			c2 = c2.ANSIStyle(FgCyan)
		case 3:
			c2 = c2.ANSIStyle(FgGreen)
		case 4:
			c2 = c2.ANSIStyle(FgGreen)
		case 5:
			c2 = c2.ANSIStyle(FgMagenta)
		case 6:
			c2 = c2.ANSIStyle(FgRed)
		case 7:
			c2 = c2.ANSIStyle(FgBlue)
		case 8:
			c2 = c2.ANSIStyle(FgYellow)
		case 9:
			c2 = c2.ANSIBold()
		case 10:
			// c2 = c2.ANSIBold()
			c2 = c2.ANSIItalic()
		// case 3:
		// 	c2 = c2.ANSIStrike()
		case 11:
			c2 = c2.ANSIUnderline()
		// case 5:
		// c2 = c2.ANSISelected()
		case 12:
			c2 = c2.ANSIDimFaint()
		case 13:
			c2 = c2.ANSIBlink()
		}
		// item.ANSISelected().Println(c2)
		self = self.Replace(item.String(), c2.String(), "\x1b[", "\x1b[0m")
		// self.Println()
	})
	return self
}

func (self Str) StatusBar(pre string) Str {
	e := Str("").ANSICursor(0, 0).ANSIEraseToEND().A(Str(pre).ANSISelected()).A(Str("\n") + self).Print()
	return e.Print()
}

func (self Str) Printf(tmp string) Str {
	fmt.Printf(tmp, self)
	return self
}

func (self Str) Print(pre ...any) Str {
	if pre != nil {
		pre = append(pre, self)
		fmt.Print(pre...)

	} else {
		fmt.Print(self)

	}
	return self
}

func join[T any](sep string, ss []T) Str {
	// cc := func(s T) any {
	// 	return s
	// }
	qs := []string{}
	List[T](ss).Each(func(i int, item T) {
		qs = append(qs, fmt.Sprint(item))
	})
	return Str(strings.Join(qs, sep))
}

func Sprintf(tmp string, obj ...any) Str {
	return Str(fmt.Sprintf(tmp, obj...))
}

func StatusShow(pre, info string) {
	preststa := Str("").ANSISave().ANSICursor(0, 0).ANSIClearThisLine()
	e := preststa + Str(pre).ANSISelected() + Str(info).ANSIBlue().ANSISelected().ANSIRestore()
	e.Print()
}

func ProgressShow(percent int, info string) {
	if percent > 100 {
		percent = 100
	}
	s := ""
	for i := 0; i < percent; i += 3 {
		s += " "
	}
	Str("").ANSISave().ANSICursor(0, 0).ANSIClearThisLine().Print()

	// if runtime.GOOS == "darwin" {
	// 	Sprintf("%%%d | %s\ninfo:%s", percent, Str(s).ANSICyan().ANSIBold().ANSIGreen().ANSISelected(), Str("").ANSIClearThisLine()+Str(info).ANSIYellow()).Print()

	// } else {
	Sprintf("%%%d | %s\ninfo:%s", percent, Str(s).ANSICyan().ANSIBold().ANSIStrike(), Str("").ANSIClearThisLine()+Str(info).ANSIYellow()).Print()
	// }
	Str("").ANSIRestore().Print()
}

func RandomStr(i int) Str {
	b := MakeBytes(i)
	rand.Read(b.Bytes())
	return b.DecodeHex()
}
